<template>
    <div id="container">
        <div id="editor-box">
            <canvas id="THREE-canvas"></canvas>
        </div>
        <div class="panel">
            <h1>外形自定义</h1>
            <h2>尺寸编辑</h2>
            <div>基础比例尺</div>
            <input type="number" v-model="scale.baseScale">
            <div>X缩放</div>
            <input type="number" v-model="scale.resetScaleX">
            <div>Y缩放</div>
            <input type="number" v-model="scale.resetScaleY">
            <div>Z缩放</div>
            <input type="number" v-model="scale.resetScaleZ">
            <button @click="changeScale">渲染</button>

            <h1>种植区域自定义</h1>
            <button @click="handleEditPlantArea">编辑【作物块形状】</button>
            <div class="crop">
                <ul class="crop-list">
                    <li v-for="(item) in cropPlotsList" :id="item.getId().toString()">
                        🌾 作物块{{ item.getId() }}
                        <button @click="handleOpenCropPlot(item)">编辑</button>
                        <button @click="handleDeleteCropPlot(item)">删除</button>
                    </li>
                </ul>
                <ul class="crop-editor">
                    作物块编辑器
                    <button @click="handleEditCropPlot('mud')">修改【土壤】</button>
                    <button @click="handleEditCropPlot('crop')">修改【农作物】</button>
                </ul>
            </div>

            <h1>道路自定义</h1>
            <button @click="changeCreateRoad">新增道路</button>
            <div class="road">
                <ul class="road-list">
                    <li v-for="(item, index) in roadList">
                        🔳 路面 {{ index + 1 }}
                        <button @click="handleOpenEditRoad(index)">编辑</button>
                        <button @click="handleRemoveRoad(index)">删除</button>
                    </li>
                </ul>
                <ul class="road-editor">
                    路面属性编辑
                    <li>宽:<input type="number" v-model="roadSize.width" /></li>
                    <li>高:<input type="number" v-model="roadSize.height" /></li>
                    <button @click="handleChangeRoad('size')">修改路面尺寸</button>
                    <button @click="handleChangeRoad('position')">修改路面位置</button>
                    <button @click="handleChangeRoad('texture')">修改路面贴图</button>
                </ul>
            </div>
            <h1>设备自定义</h1>
            <button @click="handleEditDevice('insideDevice')">添加【内部设备】</button>
            <button @click="handleEditDevice('finish')">退出【编辑】</button>
            <button @click="handleEditDevice('clear')">清空【设备】</button>
            <div class="deivce">
                <ul class="device-list">
                    <li v-for="(item, index) in deviceList">
                        ⚙ 设备{{ index + 1 }}
                        <button @click="handleOpenDevice(item)">编辑</button>
                        <button @click="handleDeleteDevice(item.id)">删除</button>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref, Ref, shallowRef } from 'vue';
import * as THREE from 'three';
import * as TWEEN from '@tweenjs/tween.js'
import Light from '@/utils/Editor/Light';
import { enableAxesHelper } from '@/utils/Editor/Helper';
import CSSManager from '@/utils/Editor/Manager/CSSManager';
// 新封装的编辑器组件
import Controls from '@/editor/Controls';
import Field from '@/editor/Field/Field';
import RoadManager from '@/editor/Field/RoadManager';
import PlantAreaManager from '@/editor/PlantAreaManager';
import DeviceManager from '@/editor/DeviceManager';
import { createCameraTween } from '@/editor/tools/useTween';

let camera, renderer;

let scene: Editor.BaseModelOption['scene'];

let cssManager: CSSManager

let light: Light;

let field: Editor.Field;

let roadManager: Editor.RoadManager;

let raycaster: THREE.Raycaster;

const scale = shallowRef({
    baseScale: 1.5,
    resetScaleX: 1,
    resetScaleY: 1,
    resetScaleZ: 1,
})


function animate() {
    requestAnimationFrame(animate);
    // tween动画更新
    TWEEN.update();
    renderer.render(scene, camera);
    cssManager && cssManager.render()
    controls && controls.update();
}


function loadingField() {
    field = new Field({
        url: '3D/field/field1.fbx',
        controls,
        scene,
        scale: {
            base: scale.value.baseScale,
            x: scale.value.resetScaleX,
            y: scale.value.resetScaleY,
            z: scale.value.resetScaleZ
        },
        plugins: [{
            name: 'PlantAreaManager',
            option: {
                camera,
                preloadCropPlotRawDatas: [
                    {
                        data: {
                            id: 1750323040203,
                        },
                        cropModelInfo: {
                            url: null,
                        },
                        pointArr: [
                            {
                                x: 0.02361295493787556,
                                y: 0.034270897415106215,
                            },
                            {
                                x: 0.3274849978961298,
                                y: 0.034270897415106215,
                            },
                            {
                                x: 0.3274849978961298,
                                y: 0.5342708974151062,
                            },
                            {
                                x: 0.02361295493787556,
                                y: 0.5342708974151062,
                            },
                        ],
                    },
                    {
                        data: {
                            id: 1750323042734,
                        },
                        cropModelInfo: {
                            url: null,
                        },
                        pointArr: [
                            {
                                x: 0.6667064160039189,
                                y: 0.4643637285179008,
                            },
                            {
                                x: 0.9705784589621731,
                                y: 0.4643637285179008,
                            },
                            {
                                x: 0.9705784589621731,
                                y: 0.9643637285179008,
                            },
                            {
                                x: 0.6667064160039189,
                                y: 0.9643637285179008,
                            },
                        ],
                    },
                ],
            }
        }, {
            name: 'DeviceManager',
            option: {
                camera,
                preloadDeviceRawDatas: [
                    {
                        id: 1751442144946,
                        type: 'insideDevice',
                        url: '3D/device/waterValve.fbx',
                        scale: {
                            base: 0.05,
                            x: 1,
                            y: 1,
                            z: 1,
                        },
                        pos: {
                            position: {
                                x: 500,
                                y: 10,
                                z: -10,
                            },
                            quaternion: {
                                x: 0.7071067811865475,
                                y: 0,
                                z: 0,
                                w: 0.7071067811865476,
                            },
                        },
                    },
                ]
            }
        }]
    })
    field.on(Field.EVENT_BASEMODEL_PLUGINS_LOADED, (plugins: Editor.Plugins) => {
        plantAreaManager = field.getPluginByName('PlantAreaManager')
        if (plantAreaManager) {
            plantAreaManager.on(PlantAreaManager.EVENT_CROP_STAFF_UPDATE, ({ cropPlots }) => {
                cropPlotsList.value = cropPlots
            })
        }
        deviceManager = field.getPluginByName('DeviceManager')
        if (deviceManager) {
            deviceManager.on(DeviceManager.EVENT_DEVICE_MANAGER_UPDATE, ({ devices }) => {
                deviceList.value = devices
            })
        }
    })
}

function changeScale() {
    field && field.changeScale({
        base: scale.value.baseScale,
        x: scale.value.resetScaleX,
        y: scale.value.resetScaleY,
        z: scale.value.resetScaleZ
    })
}

const roadList: Ref<Array<Editor.Road>> = ref([])
const roadSize = shallowRef({
    width: 10,
    height: 1
})
let selectedRoadIndex = -1

function changeCreateRoad() {
    if (!roadManager) {
        roadManager = new RoadManager({
            field,
            controls,
            camera,
            scene,
            raycaster,
            renderer,
        })
        roadManager.on(RoadManager.EVENT_ROAD_MANAGER_UPDATE, (params) => {
            // road是mesh的集合
            const { roads } = params
            roadList.value.splice(0, roadList.value.length);
            roads.forEach(road => roadList.value.push(road));
        })
    }
    roadManager.createRoad({ url: '3D/mud/mud1.png' })

}


function handleOpenEditRoad(index) {
    /**
     * TODO:
     * 视角聚焦(待定)
     * index保留
     */
    selectedRoadIndex = index
}

function handleRemoveRoad(index) {
    roadManager && roadManager.removeRoad(index)
}

/**
 * @param type {'size' | 'position' | 'texture' | 'remove'}
 */
function handleChangeRoad(type) {
    const road = roadList.value[selectedRoadIndex]
    if (!road) return
    switch (type) {
        case 'size': {
            road.changeSize({ width: roadSize.value.width, height: roadSize.value.height })
        } break;
        case 'position': {
            road.changePosition(controls)
        } break;
        case 'texture': {
            road.changeTexture('3D/mud/mud2.png')
        } break;
    }
}

let plantAreaManager: PlantAreaManager;
function handleEditPlantArea() {
    if (!plantAreaManager) return;
    plantAreaManager.enableShapeEditor()

}

const cropPlotsList: Ref<Array<Editor.CropPlot>> = ref([])
let selectedCropPlotId: string | number = null
const handleOpenCropPlot = (item: Editor.CropPlot) => {
    // 这里存储ID是安全的做法, 如果将选中的plot删除，再编辑会导致错误
    selectedCropPlotId = item.getId()
    // TWEEN飞入
    const box = new THREE.Box3().setFromObject(item.model)
    const center = box.getCenter(new THREE.Vector3());
    const endPos = center.clone().addScalar(100)
    endPos.y += 100
    const endTarget = center.clone().addScalar(50)
    createCameraTween({ camera, controls: controls.orbitControls, endPos, endTarget, duration: 500 })
}

const handleDeleteCropPlot = (item: Editor.CropPlot) => {
    const id = item.getId()
    plantAreaManager.removeCropPlotById(id)

}

function handleEditCropPlot(type: string) {
    const cropPlot = plantAreaManager.getCropPlotById(selectedCropPlotId)
    if (cropPlot) {
        switch (type) {
            case 'mud': {
                /** FIXME:效果有问题 */
                cropPlot.changeMud({ url: '3D/mud/mud1.png' })
            } break;
            case 'crop': {
                cropPlot.changeCrop({ url: '3D/carrot.fbx', scale: 1 })
            } break;
        }
    }

}

let deviceManager: Editor.DeviceManager = null

const deviceList: Ref<Array<Editor.Device>> = ref([])
const handleEditDevice = (type) => {
    if (!deviceManager) return;
    switch (type) {
        case 'insideDevice':
            deviceManager.createDevice({
                type,
                url: '3D/device/waterValve.fbx',
                scale: {
                    base: 0.1,
                },
                autoLoad: true,
            })
            break;
        case 'finish':
            deviceManager.closeEdit()
            break;
        case 'clear': {
            deviceManager.removeAllDevices()
        } break;
        default:
            break;
    }
}

const handleOpenDevice = (item: Editor.Device) => {
    if (!deviceManager) return;
    deviceManager.openEdit(item)
}
const handleDeleteDevice = (id: string | number) => {
    if (!deviceManager) return;
    deviceManager.removeDeviceById(id)
}

let controls: Editor.Controls;

function init() {
    const box = document.getElementById('THREE-canvas');
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(75, box.clientWidth / box.clientHeight, 0.1, 5000);
    // camera.position.set(500 + 200, 1000, 200);
    camera.position.set(200, 200, 100);
    renderer = new THREE.WebGLRenderer({ antialias: true, canvas: box });
    renderer.setSize(box.clientWidth, box.clientHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setClearColor(0x000000);

    enableAxesHelper(scene)
    raycaster = new THREE.Raycaster();

    light = new Light({ scene })
    // 添加网格辅助线
    const grid = new THREE.GridHelper(2000, 50, 0xffffff, 0xffffff);
    grid.material.opacity = 0.2;
    grid.material.transparent = true;
    scene.add(grid);

    // 创建控制器
    controls = new Controls({
        camera,
        scene,
        renderer,
        boxId: 'editor-box'
    })

    // 创建CSS管理器
    cssManager = new CSSManager({ camera, scene, renderer, containerId: 'editor-box' })
    loadingField()
    animate()

}

onMounted(() => {
    init();
});

onBeforeUnmount(() => {
    if (renderer) renderer.dispose();
    field && field.destroy()
});
</script>


<style lang="scss" scoped>
#container {
    width: 100%;
    height: 100%;
    display: flex;
    $panelWidth: 20%;

    #editor-box {
        width: calc(100% - #{$panelWidth});
        height: 100%;
        position: relative;

        #THREE-canvas {
            width: 100%;
            height: 100%;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 1;
        }
    }

    .panel {
        overflow-y: scroll;
        display: flex;
        flex-direction: column;
        width: $panelWidth;
        height: 100%;
        background-color: #fff;
        padding: 10px;

        input {
            width: 60%;
            margin-bottom: 5px;
        }
    }

    .crop {
        width: 100%;
        display: flex;
        margin-top: 10px;

        .crop-list {
            width: 50%;
        }

        .crop-editor {
            width: 50%;
            background-color: whitesmoke;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;

        }
    }

    .road {
        width: 100%;
        display: flex;
        margin-top: 10px;

        .road-list {
            width: 50%;
        }

        .road-editor {
            width: 50%;
            background-color: whitesmoke;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;

        }
    }

    .device {
        width: 100%;
        display: flex;
        margin-top: 10px;

        .device-list {
            width: 50%;
        }
    }
}
</style>